import { IMDSkillConfig, PlayerSkillField } from "../config/SkillConfig";
import { UnitBaseAttrConfig } from "../config/UnitBaseAttrConfig";
import { I2IDCache } from "../constant/IdCache";
import UnitX from "../entity/UnitX";
import { UnitConfig } from "../types/L_Type";
import L_Run from "../utils/L_Run";


type UnitSkillAttr={
    skillIdStr:string,
    skillLvl:number,
    lType:string,
    lvlUpExpParams:number, //升级exp系数
    enable:boolean, //是否启用状态  适用于躲技能的临时'遗忘'系统
    totalExp:number //过去学习的经验值
}


/**
 * 单位技能管理
 * 主要是单位学习技能的管理
 */
export default class UnitSkillManager {

    private static GLOBAL_SKILL_LEARN_MAP:Map<number,Array<UnitSkillAttr>>;   //unitXId->UnitSkillField

    /**下一级的基础经验值需求 */
    public static LVL_2_EXP_BASE=100;

    public unitLearnSkill(ux:UnitX,skillIdStr:string,exp:number,unLearnCompensateFunc:Function,rpFlag?:boolean){
       
        //找到技能 从config获取单位学习类型
        let susf:PlayerSkillField | undefined=this.getSkillSimpleAttr(skillIdStr)
        if(susf==undefined){
            console.log("[ERROR]无法找到正确的技能配置，",skillIdStr)
            return
        }

        //判断单位是否有槽位学习技能 TODO  已经分了技能类型了还需要限制槽位吗   例如单位职能学3个技能 那QWER应该选哪3个位置来放技能呢?  还是严格使用配置来限定 
        let usf=UnitSkillManager.GLOBAL_SKILL_LEARN_MAP.get(ux.unitXId)
        let newTmpUnitSkillAttr={...{skillIdStr,skillLvl:0,totalExp:0,enable:true},...susf}   //技能等级在addTypeAbilityForUnit方法中统一修改 exp也是
        if(usf==undefined){
            //1.什么都没学的状态
            usf=[newTmpUnitSkillAttr] 
            //调用技能添加Func
            this.addTypeAbilityForUnit(newTmpUnitSkillAttr,ux.unit,skillIdStr,exp)

            UnitSkillManager.GLOBAL_SKILL_LEARN_MAP.set(ux.unitXId,usf)
        }else{
            //有历史学习记录的情况
            let enableLTypeSkillArr=usf.filter(c=>c.lType==(susf?.lType || '') && c.enable==true)
            //当前启用的同类型技能
            let enableOtherSameLTypeSkillAttr=enableLTypeSkillArr.length==0?undefined:enableLTypeSkillArr[0]
            let targetSameAsEnable=(enableOtherSameLTypeSkillAttr?.skillIdStr || 'undefiend' )==skillIdStr

            if(targetSameAsEnable){
                //2.学习和启用是同一技能  直接提升等级
                this.addTypeAbilityForUnit(enableLTypeSkillArr[0],ux.unit,skillIdStr,exp,undefined,true)
            }else if(enableOtherSameLTypeSkillAttr!=undefined){
                //3.学习和启用不是同一技能
                let hisLearnRecordArr=usf.filter(c=>c.skillIdStr==skillIdStr)
                let curRelSkillAttr=hisLearnRecordArr.length==0?newTmpUnitSkillAttr:hisLearnRecordArr[0]   //找到了历史学习记录就使用历史  否则使用新的
                //是否替换确认FUNC
                let rpFunc=(confirm:boolean)=>{
                    if(confirm){
                        this.addTypeAbilityForUnit(curRelSkillAttr,ux.unit,skillIdStr,exp,enableOtherSameLTypeSkillAttr,false)
                    }else{
                        unLearnCompensateFunc()
                    }
                }
                //TODO FOR TEST
                if(rpFlag){
                    rpFunc(true);
                }
                //TODO  UI调用确认函数
            }else if(enableOtherSameLTypeSkillAttr==undefined){
                //4.没找到同类型技能
                usf.push(newTmpUnitSkillAttr)
                this.addTypeAbilityForUnit(newTmpUnitSkillAttr,ux.unit,skillIdStr,exp)
            }


        }
    }

    /**找到技能的学习类型*/
    public getSkillSimpleAttr(skillIdStr:string):PlayerSkillField | undefined{
        let skillConfig=IMDSkillConfig[skillIdStr]

        //TODO
        if(skillConfig!=undefined && skillConfig.playerSkillField!=undefined){
           return {'lType':skillConfig.playerSkillField!.lType,'lvlUpExpParams':skillConfig.playerSkillField!.lvlUpExpParams}
        }else{
           return undefined
        }
        
   }
   


    private addTypeAbilityForUnit(relUnitSkillAttr:UnitSkillAttr,u:unit,skillIdStr:string,curAddExp:number,replaceUnitSkillAttr?:UnitSkillAttr,setSkillLvlOnly?:boolean){
        //根据经验值计算当前技能等级
        let totalExp=relUnitSkillAttr.totalExp+curAddExp
        let sLvl=this.expTrsfSkillLvl(totalExp,relUnitSkillAttr.lvlUpExpParams)
        //如果是替换技能先移除技能
        if(replaceUnitSkillAttr!=undefined){
            replaceUnitSkillAttr.enable=false
            L_Run.UnitRemoveAbility(u,replaceUnitSkillAttr.skillIdStr)
        }
        //添加技能并且设置等级
        if(setSkillLvlOnly==true){
            L_Run.UnitAddAbilityWithLvl(u,skillIdStr,sLvl)
        }else{
            L_Run.UnitSetAbilityLvl(u,skillIdStr,sLvl)
        }

        relUnitSkillAttr.enable=true   //无论何时都修改一下状态
    }

    private expTrsfSkillLvl(exp:number,lvlUpExpParams:number):number{
        let base=UnitSkillManager.LVL_2_EXP_BASE   //第二级技能要的经验 例如系数1.2 下 [100 ,120,144,172...]
        let rs=0
        if(exp<base){
            return 1
        }else{
            let lstExp=exp
            while(lstExp>0){
                lstExp=lstExp-base
                rs=rs+1
                base=base*lvlUpExpParams
            }
        }
        if(rs>9){
            rs=9
        }
        return rs
    }

    
}